/*
 * @Author: soso
 * @Date: 2022-02-07 13:53:36
 * @LastEditTime: 2022-03-11 15:52:34
 * @LastEditors: Please set LastEditors
 * @Description: 倒序读取的文件序列，不支持删除，适用于备份
 * @FilePath: /go-mesh-sync/go-utils/lazyfile/lazyfile.go
 */

package revfile

import (
	"bufio"
	"encoding/binary"
	"io"
	"log"
	"os"
)

type Revfile struct {
	path string
}

// 新建一个反向文件
func NewRevFile(path string) (out Revfile) {
	out = Revfile{}
	out.path = path

	return
}

// 读取数据
func (rf Revfile) Read(cbFunc func(data []byte) (ctn bool)) {
	if cbFunc == nil {
		panic("must have a callback func")
	}

	_, err := os.Stat(rf.path)
	if os.IsNotExist(err) {
		return
	}

	f, err := os.OpenFile(rf.path, os.O_RDONLY, os.ModePerm)
	if err != nil {
		log.Println(err)
		return
	}
	defer f.Close()

	var offset int64 = 0
	var dataLen uint32
	for {
		offset -= 4
		_, err := f.Seek(offset, io.SeekEnd)
		if err != nil {
			log.Println(err)
			return
		}

		if err := binary.Read(f, binary.LittleEndian, &dataLen); err != nil {
			log.Println(err)
			return
		}

		offset -= int64(dataLen)
		_, err = f.Seek(offset, io.SeekEnd)
		if err != nil {
			log.Println(err)
			return
		}

		buf := make([]byte, dataLen)

		if _, err := io.ReadFull(f, buf); err != nil {
			log.Println(err)
			return
		}
		if !cbFunc(buf) {
			return
		}
	}
}

//添加数据
func (rf Revfile) Append(datas [][]byte) error {
	f, err := rf.Openfile()
	if err != nil {
		log.Panicln(err)
		return err
	}
	defer f.Close()

	wt := bufio.NewWriter(f)
	defer wt.Flush()

	var datalen uint32
	for _, data := range datas {
		nn, err := wt.Write(data)
		if err != nil {
			log.Println(err)
			return err
		}

		datalen = uint32(nn)

		if err := binary.Write(wt, binary.LittleEndian, datalen); err != nil {
			log.Println(err)
			return err
		}
	}
	return nil
}

// Append方式打开文件
func (rf Revfile) Openfile() (f *os.File, err error) {
	return os.OpenFile(rf.path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
}
